#!/bin/bash
#
# gce-load-kernel -- this script handles switching to the kernel to be
# tested (using either kexec or by installing kernel debian packages),
# as well as one-time setups that we want to do as early as possible
# (such as unpacking any modules or modifications to the test
# appliance via xfstests.tar.gz and files.tar.gz).

. /usr/local/lib/gce-funcs

if grep -q fstestcfg /proc/cmdline; then exit 0; fi

if test -f /root/do_kexec ; then
    /usr/local/lib/gce-logger do_kexec file found, using it
    . /root/do_kexec
fi

gcloud config set compute/zone $ZONE

if ! test -d /root/hooks
then
    mkdir -p /root/hooks
    hooks=$(gce_attribute hooks)
    if test -n "$hooks"
    then
	gsutil cp $hooks /run/hooks.tar.gz
	if test -f /run/hooks.tar.gz
	then
	    tar -C /root/hooks -xzf /run/hooks.tar.gz
	    rm /run/hooks.tar.gz
	fi
    fi
fi

kexec=$(gce_attribute kexec)

kopt=$(gce_attribute kopt | sed -e 's/:/ /')
cmd=$(gce_attribute cmd)
mem=$(gce_attribute mem)
cpus=$(gce_attribute nr_cpus)
mount_opts=$(gce_attribute mount_opts)
disk_spec=$(gce_attribute disk_spec)
pts_size=$(gce_attribute pts_size)
fstestcfg=$(gce_attribute fstestcfg)
fstestset=$(gce_attribute fstestset)
fstestexc=$(gce_attribute fstestexc)
fstestopt=$(gce_attribute fstestopt)
fstesttz=$(gce_attribute fstesttz)
fstesttyp=$(gce_attribute fstesttyp)
fstestapi=$(gce_attribute fstestapi)
fsteststr=$(gce_attribute fsteststr)
orig_cmdline=$(gce_attribute orig_cmdline)
tarxfstests=$(gce_attribute tarxfstests)
tarfiles=$(gce_attribute tarfiles)
tarmodules=$(gce_attribute tarmodules)
nfssrv=$(gce_attribute nfssrv)

if test -n "$tarxfstests" ; then
    gsutil cp "$tarxfstests" /run/xfstests.tar.gz
    rm -rf /root/xfstests
    tar -C /root -xzf /run/xfstests.tar.gz
    rm /run/xfstests.tar.gz
fi

if test -n "$tarfiles" ; then
    gsutil cp "$tarfiles" /run/files.tar.gz
    tar -C / -xzf /run/files.tar.gz
    rm /run/files.tar.gz
    sed -e 's;/dev/;/dev/mapper/xt-;' < /root/test-config > /tmp/test-config
    echo "export RUN_ON_GCE=yes" >> /tmp/test-config
    mv /tmp/test-config /root/test-config
    rm -f /root/*~
    chown root:root /root
fi

if test -n "$tarmodules" ; then
    gsutil cp "$tarmodules" /run/modules.tar.xz
    tar -C / -xJf /run/modules.tar.xz
    rm /run/modules.tar.xz
    depmod -a
fi

if test -z "$kexec"
then
    /usr/local/lib/gce-add-metadata "kernel_version=$(uname -a)" &
    cat >> /run/test-env <<EOF
# Appended by gce-kexec
ORIG_CMDLINE="${orig_cmdline}"
FSTESTCFG="${fstestcfg//,/ }"
FSTESTSET="${fstestset//,/ }"
FSTESTOPT="${fstestopt//,/ }"
FSTESTTYP="$fstesttyp"
FSTESTAPI="${fstestapi//./ }"
FSTESTSTR="${fsteststr//,/ }"
timezone="$fstesttz"
MNTOPTS="$mount_opts"
DISK_SPEC="$disk_spec"
PTS_SIZE="$pts_size"
FSTESTEXC="${fstestexc//,/ }"
NFSSRV="$nfssrv"
EOF
    exit 0
fi

if test -n "$fstesttz" -a -f /usr/share/zoneinfo/$fstesttz
then
    ln -sf /usr/share/zoneinfo/$fstesttz /etc/localtime
    echo $fstesttz > /etc/timezone
fi

if test -n "$cmd"
then
    kopt="$kopt cmd=${cmd}"
fi

if test -n "$mem"
then
    kopt="$kopt mem=${mem}M"
fi

if test -n "$cpus"
then
    kopt="$kopt maxcpus=$cpus"
fi

if test -n "$mount_opts"
then
    kopt="$kopt mount_opts=$mount_opts"
fi

if test -n "$disk_spec"
then
    kopt="$kopt disk_spec=$disk_spec"
fi

if test -n "$pts_size"
then
    kopt="$kopt pts_size=$pts_size"
fi

kopt="console=ttyS0,115200 earlyprintk=ttyS0,115200 elevator=noop console=ttyS0 net.ifnames=0 biosdevname=0 $kopt fstestcfg=$fstestcfg fstestset=$fstestset fstestexc=$fstestexc fstestopt=$fstestopt fstesttyp=$fstesttyp fstestapi=$fstestapi fsteststr=$fsteststr nfssrv=$nfssrv orig_cmdline=$orig_cmdline"

if [[ $kexec == *.deb ]] ; then
    cat > /etc/default/grub.d/50-xfstests-cmd.cfg <<EOF
# This file was generated by /usr/local/lib/gce-load-kernel

GRUB_CMDLINE_LINUX="$kopt"
EOF
    if ! test -f "/root/kernel-deb.deb" ; then
	if ! gsutil cp $kexec /root/kernel-deb.deb ; then
	    echo "gsutil cp $kexec /root/kernel-deb.deb failed"
	    exit 1
	fi
    fi
    retry=0
    while ! dpkg -i /root/kernel-deb.deb ; do
	sleep 5
	(( retry++ ))
	if test "$retry" -gt 36 ; then
	    logger "Kernel installation failed after multiple retries"
	    exit 1
	fi
    done
    logger "Installation succeeded ($retry retries required)"
    kernel=$(dpkg -c /root/kernel-deb.deb  | grep "vmlinuz" | rev | cut -d "/" -f1 | rev | cut -d "-" -f2-)
    menuline=$(grep -i "menuentry '" /boot/grub/grub.cfg|sed -r "s|--class .*$||g" | grep -ne $kernel | grep -v recovery | cut -f1 -d":")
    menunum=$(($menuline-2))
    logger "Using grub-reboot 1>$menunum"
    grub-reboot "1>$menunum"
    echo "Rebooting..."
    reboot
fi

if ! test -f /root/bzImage
then
    if ! gsutil cp $kexec /root/bzImage
    then
	logger "Couldn't find $kexec"
	exit 1
    fi
    sync
fi

cat > /root/do_kexec <<EOF
run_hooks kexec
/usr/local/lib/gce-logger kexec to test kernel
systemctl stop rsyslog.service
sync
kexec /root/bzImage --command-line="root=/dev/sda1 ro $kopt"
/usr/local/lib/gce-logger kexec failed?!?
exit 1
EOF

retry=0
while fuser /var/lib/dpkg/lock >/dev/null 2>&1 ; do
    sleep 5
    (( retry++ ))
    if test "$retry" -gt 36 ; then
	logger "/var/lib/dpkg/lock held for too long"
	break
    fi
done

. /root/do_kexec
